﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Bohdan.Arch.Messaging;
using Bohdan.Arch.Messaging.Special;
using System.Threading;

namespace Bohdan.Arch.Messaging.Actors
{
    public class PulsarActor
    {
        protected enum State { NonBeating, Beating };

        protected State _State = State.NonBeating;
        protected MessagingBus _Bus;
        protected TimeSpan _Interval;
        protected EventWaitHandle _ewhStopBeating;
        protected Thread _thHeart;

        public Action Action { get; set; }

        public MessagingBus Bus
        {
            get
            {
                lock (this)
                {
                    return _Bus;
                }
            }
            set
            {
                lock (this)
                {
                    _Bus = value;
                }
            }
        }
        public TimeSpan Interval
        {
            get
            {
                lock (this)
                {
                    return _Interval;
                }
            }
            set
            {
                lock (this)
                {
                    _Interval = value;
                }
            }
        }
        public bool IgnoreSubsequentCommands { get; set; }

        protected void WorkerThread()
        {
            while (true)
            {
                if (!_ewhStopBeating.WaitOne(Interval))
                    Bus.PostMessageAsync(new SimpleActionMessage(Action));
                else
                    break;
            }
        }

        public PulsarActor()
        {
            IgnoreSubsequentCommands = false;
        }

        public void Start()
        {
            lock (this)
            {
                if (_State == State.Beating)
                {
                    if (!IgnoreSubsequentCommands)
                        throw new ArgumentException("Pulsar is already beating.");
                    return;
                }

                _State = State.Beating;
            }

            _ewhStopBeating = new EventWaitHandle(false, EventResetMode.ManualReset);

            _thHeart = new Thread(WorkerThread);
            _thHeart.Priority = ThreadPriority.Highest;
            _thHeart.Start();

        }

        public void Stop()
        {
            lock (this)
            {
                if (_State == State.NonBeating)
                {
                    if (!IgnoreSubsequentCommands)
                        throw new ArgumentException("Pulsar isn't beating yet.");
                    return;
                }

                _State = State.NonBeating;
            }

            _ewhStopBeating.Set();
            _thHeart.Join();
        }
    }
}
